﻿using System;
using System.Collections.Generic;
using System.Text;

namespace OkTool.Util
{
    /// <summary>
    /// Bool类型相关工具类
    /// </summary>
    public class BoolUtil
    {
        private static readonly HashSet<string> TRUE_SET = new HashSet<string> { "true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真", "對", "√" };
        private static readonly HashSet<string> FALSE_SET = new HashSet<string> { "false", "no", "n", "f", "0", "off", "否", "错", "假", "錯", "×" };

        /// <summary>
        /// 取相反值
        /// </summary>
        /// <param name="boolValue"></param>
        /// <returns></returns>
        public static bool? Negate(bool? boolValue)
        {
            return boolValue != null ? !boolValue : (bool?)null;
        }

        /// <summary>
        /// 检查 {@code Boolean} 值是否为 {@code true}
        /// </summary>
        /// <param name="boolValue"></param>
        /// <returns></returns>
        public static bool IsTrue(bool? boolValue)
        {
            return boolValue == true;
        }

        /// <summary>
        /// 检查 {@code Boolean} 值是否为 {@code false}
        /// </summary>
        /// <param name="boolValue"></param>
        /// <returns></returns>
        public static bool IsFalse(bool? boolValue)
        {
            return boolValue == false;
        }

        /// <summary>
        /// 取相反值
        /// </summary>
        /// <param name="boolValue"></param>
        /// <returns></returns>
        public static bool Negate(bool boolValue)
        {
            return !boolValue;
        }

        /// <summary>
        /// 转换字符串为boolean值
        /// </summary>
        /// <param name="valueStr"></param>
        /// <returns></returns>
        public static bool ToBoolean(string valueStr)
        {
            if (!string.IsNullOrWhiteSpace(valueStr))
            {
                valueStr = valueStr.Trim().ToLower();
                return TRUE_SET.Contains(valueStr);
            }
            return false;
        }

        /// <summary>
        /// 转换字符串为boolean值
        /// <para>如果为["true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真", "對", "√"]，返回{@code true}</para>
        ///  <para>如果为["false", "no", "n", "f", "0", "off", "否", "错", "假", "錯", "×"]，返回{@code false}</para>
        ///  <para>其他情况返回 null</para>
        /// </summary>
        /// <param name="valueStr"></param>
        /// <returns></returns>
        public static bool? ToBooleanObject(string valueStr)
        {
            if (!string.IsNullOrWhiteSpace(valueStr))
            {
                valueStr = valueStr.Trim().ToLower();
                if (TRUE_SET.Contains(valueStr))
                {
                    return true;
                }
                if (FALSE_SET.Contains(valueStr))
                {
                    return false;
                }
            }
            return null;
        }

        /// <summary>
        /// boolean值转为Integer
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int ToInt(bool value)
        {
            return value ? 1 : 0;
        }


        /// <summary>
        /// boolean值转为char
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static char ToChar(bool value)
        {
            return (char)ToInt(value);
        }

        /// <summary>
        /// boolean值转为byte
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static byte ToByte(bool value)
        {
            return (byte)ToInt(value);
        }


        /// <summary>
        /// boolean值转为long
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long ToLong(bool value)
        {
            return ToInt(value);
        }

        /// <summary>
        /// boolean值转为short
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static short ToShort(bool value)
        {
            return (short)ToInt(value);
        }


        /// <summary>
        /// boolean值转为float
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static float ToFloat(bool value)
        {
            return (float)ToInt(value);
        }

        /// <summary>
        /// boolean值转为double
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static double ToDouble(bool value)
        {
            return ToInt(value);
        }

        /// <summary>
        /// 将boolean转换为字符串 {@code 'true'} 或者 {@code 'false'}.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToStringTrueFalse(bool value)
        {
            return ToString(value, "true", "false");
        }
        /// <summary>
        /// 将boolean转换为字符串 {@code 'on'} 或者 {@code 'off'}.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToStringOnOff(bool value)
        {
            return ToString(value, "on", "off");
        }
        /// <summary>
        /// 将boolean转换为字符串 {@code 'yes'} 或者 {@code 'no'}.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ToStringYesNo(bool value)
        {
            return ToString(value, "yes", "no");
        }

        /// <summary>
        /// 将boolean转换为字符串
        /// </summary>
        /// <param name="value"></param>
        /// <param name="trueString">当值为 {@code true}时返回此字符串, 可能为 {@code null}</param>
        /// <param name="falseString">当值为 {@code false}时返回此字符串, 可能为 {@code null}</param>
        /// <returns></returns>
        public static string ToString(bool value, string trueString, string falseString)
        {
            return value ? trueString : falseString;
        }

        /// <summary>
        /// 将boolean转换为字符串
        /// </summary>
        /// <param name="value"></param>
        /// <param name="trueString">当值为 {@code true}时返回此字符串, 可能为 {@code null}</param>
        /// <param name="falseString">当值为 {@code false}时返回此字符串, 可能为 {@code null}</param>
        /// <param name="nullString">当值为 {@code null}时返回此字符串, 可能为 {@code null}</param>
        /// <returns></returns>
        public static string ToString(bool? value, string trueString, string falseString, string nullString)
        {
            if (value == null)
            {
                return nullString;
            }
            return value.Value ? trueString : falseString;
        }

        /// <summary>
        /// 对Boolean数组取与
        ///<para> BooleanUtil.and(true, true)         = true</para>
        ///<para> BooleanUtil.and(false, false)       = false</para>
        ///<para> BooleanUtil.and(true, false)        = false</para>
        ///<para> BooleanUtil.and(true, true, false)  = false</para>
        ///<para> BooleanUtil.and(true, true, true)   = true</para>
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static bool And(params bool[] array)
        {
            if (array == null || array.Length == 0)
            {
                throw new ArgumentException("The Array must not be empty !");
            }
            foreach (bool element in array)
            {
                if (!element)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 对Boolean数组取与
        ///<para> BooleanUtil.AndOfWrap(Boolean.TRUE, Boolean.TRUE)                 = Boolean.TRUE</para>
        ///<para> BooleanUtil.AndOfWrap(Boolean.FALSE, Boolean.FALSE)               = Boolean.FALSE</para>
        ///<para> BooleanUtil.AndOfWrap(Boolean.TRUE, Boolean.FALSE)                = Boolean.FALSE</para>
        ///<para> BooleanUtil.AndOfWrap(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)   = Boolean.TRUE</para>
        ///<para> BooleanUtil.AndOfWrap(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE) = Boolean.FALSE</para>
        ///<para> BooleanUtil.aAndOfWrapnd(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE)  = Boolean.FALSE</para>
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static bool? AndOfWrap(params bool?[] array)
        {
            if (array == null || array.Length == 0)
            {
                throw new ArgumentException("The Array must not be empty !");
            }
            foreach (bool? b in array)
            {
                if (!IsTrue(b))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 对Boolean数组取或
        ///<para>BooleanUtil.or(true, true)          = true</para>
        ///<para>BooleanUtil.or(false, false)        = false</para>
        ///<para>BooleanUtil.or(true, false)         = true</para>
        ///<para>BooleanUtil.or(true, true, false)   = true</para>
        ///<para>BooleanUtil.or(true, true, true)    = true</para>
        ///<para>BooleanUtil.or(false, false, false) = false</para>
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static bool Or(params bool[] array)
        {
            if (array == null || array.Length == 0)
            {
                throw new ArgumentException("The Array must not be empty !");
            }
            foreach (bool element in array)
            {
                if (element)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 对Boolean数组取或
        ///<para>BooleanUtil.or(Boolean.TRUE, Boolean.TRUE)                  = Boolean.TRUE</para>
        ///<para>BooleanUtil.or(Boolean.FALSE, Boolean.FALSE)                = Boolean.FALSE</para>
        ///<para>BooleanUtil.or(Boolean.TRUE, Boolean.FALSE)                 = Boolean.TRUE</para>
        ///<para>BooleanUtil.or(Boolean.TRUE, Boolean.TRUE, Boolean.TRUE)    = Boolean.TRUE</para>
        ///<para>BooleanUtil.or(Boolean.FALSE, Boolean.FALSE, Boolean.TRUE)  = Boolean.TRUE</para>
        ///<para> BooleanUtil.or(Boolean.TRUE, Boolean.FALSE, Boolean.TRUE)   = Boolean.TRUE</para>
        ///<para>BooleanUtil.or(Boolean.FALSE, Boolean.FALSE, Boolean.FALSE) = Boolean.FALSE</para>
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static bool? OrOfWrap(params bool?[] array)
        {
            if (array == null || array.Length == 0)
            {
                throw new ArgumentException("The Array must not be empty !");
            }
            foreach (bool? b in array)
            {
                if (IsTrue(b))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 对Boolean数组取异或
        /// <para>   BooleanUtil.xor(true, true)   = false</para>
        /// <para>  BooleanUtil.xor(false, false) = false</para>
        /// <para>  BooleanUtil.xor(true, false)  = true</para>
        /// <para>  BooleanUtil.xor(true, true)   = false</para>
        /// <para>  BooleanUtil.xor(false, false) = false</para>
        /// <para>  BooleanUtil.xor(true, false)  = true</para>
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static bool Xor(params bool[] array)
        {
            if (array == null || array.Length == 0)
            {
                throw new ArgumentException("The Array must not be empty");
            }
            bool result = false;
            foreach (bool element in array)
            {
                result ^= element;
            }
            return result;
        }

        /// <summary>
        /// 对Boolean数组取异或
        /// <para> BooleanUtil.xor(new Boolean[] { Boolean.TRUE, Boolean.TRUE })    = Boolean.FALSE</para>
        /// <para> BooleanUtil.xor(new Boolean[] { Boolean.FALSE, Boolean.FALSE })  = Boolean.FALSE</para>
        /// <para> BooleanUtil.xor(new Boolean[] { Boolean.TRUE, Boolean.FALSE })   = Boolean.TRUE</para>
        /// </summary>
        /// <param name="array"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static bool? XorOfWrap(params bool?[] array)
        {
            if (array == null || array.Length == 0)
            {
                throw new ArgumentException("The Array must not be empty !");
            }
            bool[] primitive = Array.ConvertAll(array, item => item ?? false);
            return Xor(primitive);
        }

        /// <summary>
        /// 给定类是否为Boolean或者boolean
        /// </summary>
        /// <param name="clazz"></param>
        /// <returns></returns>
        public static bool IsBoolean(Type clazz)
        {
            return (clazz == typeof(bool) || clazz == typeof(bool?));
        }


    }
}
